package com.lisa.auto.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.carrotsearch.sizeof.RamUsageEstimator;
import com.lisa.auto.entity.C3ReportCarFault;
import com.lisa.auto.entity.C3ReportEventInfo;
import com.lisa.auto.entity.C3RiskConfiguration;
import com.lisa.auto.entity.C3RiskFault;
import com.lisa.auto.mapper.C3ReportCarFaultMapper;
import com.lisa.auto.service.*;
import com.lisa.auto.util.DateUtil;
import com.lisa.syslog.SysLogUtil;
import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @description: 车辆故障上报Service Impl
 * @author: huangzhigang
 * @date: 2020-03-13 11:24
 **/
@Service
public class C3ReportCarFaultServiceImpl extends ServiceImpl<C3ReportCarFaultMapper, C3ReportCarFault> implements C3ReportCarFaultService {

    private static final Logger logger = LoggerFactory.getLogger(C3ReportCarFaultServiceImpl.class);

    @Autowired
    private C3RiskConfigurationService riskConfigurationService;

    @Autowired
    private C3FaultConfigurationService faultConfigurationService;
    @Autowired
    private C3RiskFaultService riskFaultService;
    @Autowired
    private C3ReportEventInfoService reportEventInfoService;
    /**
     * 车辆故障上报
     * @param map
     */
    @Override
    public void reportCarFault(Map<String, Object> map) {
        long start = System.currentTimeMillis();
        List<C3ReportCarFault> faultList = JSON.parseArray((String) map.get("list"), C3ReportCarFault.class);
        EntityWrapper<C3RiskConfiguration> ew = new EntityWrapper<>();
        List<C3RiskConfiguration> c3RiskConfigurations = riskConfigurationService.selectList(ew);
        if (CollectionUtils.isNotEmpty(faultList)){
            faultList.stream().forEach(fault->{
                c3RiskConfigurations.stream().forEach(riskConfig->{
                    loadConfig(riskConfig,fault);
                });
                baseMapper.insert(fault);
            });
        }
        long end =System.currentTimeMillis();
        logger.info("风险故障Time:{}",end-start);
        //System.out.println(RamUsageEstimator.sizeOf(maps));
    }

    /**
     * 车辆故障上报
     * @param faultList
     */
    @Override
    public void reportCarFault(List<C3ReportCarFault> faultList) {
        long start = System.currentTimeMillis();
        EntityWrapper<C3RiskConfiguration> ew = new EntityWrapper<>();
        List<C3RiskConfiguration> c3RiskConfigurations = riskConfigurationService.selectList(ew);
        if (CollectionUtils.isNotEmpty(faultList)){
            faultList.stream().forEach(fault->{
                c3RiskConfigurations.stream().forEach(riskConfig->{
                    loadConfig(riskConfig,fault);
                });
                baseMapper.insert(fault);
            });
        }
        long end =System.currentTimeMillis();
        logger.info("风险故障Time:{}",end-start);
        //System.out.println(RamUsageEstimator.sizeOf(maps));
    }

    //List<Map<String, String>> vehicleFaultList = new ArrayList<>();
    Map<String, Map<String,String>>  maps = new HashMap<>();
    public void loadConfig(C3RiskConfiguration riskConfig,C3ReportCarFault fault) {
        try {

            switch (riskConfig.getEventId()) {
                case "ALARM001":
                    loadRiskFault(fault.getVehicleFault(),fault.getVin(),"ALARM001",riskConfig,fault);
                    break;
                case "ALARM002":
                    //loadRiskFault(fault.getVehicleChargeFault(),riskConfig,fault);
                    loadRiskFault(fault.getVehicleChargeFault(),fault.getVin(),"ALARM002",riskConfig,fault);
                    break;
                case "ALARM003":
                    //loadRiskFault(fault.getVehicleHighVoltageInterLockFault(),riskConfig,fault);
                    loadRiskFault(fault.getVehicleHighVoltageInterLockFault(),fault.getVin(),"ALARM003",riskConfig,fault);
                    break;
                case "ALARM004":
                    //loadRiskFault(fault.getBrakingSysFault(),riskConfig,fault);
                    loadRiskFault(fault.getBrakingSysFault(),fault.getVin(),"ALARM004",riskConfig,fault);
                    break;
                case "ALARM005":
                    //loadRiskFault(fault.getBatteryOverCharge(),riskConfig,fault);
                    loadRiskFault(fault.getBatteryOverCharge(),fault.getVin(),"ALARM005",riskConfig,fault);
                    break;
                case "ALARM006":
                    //loadRiskFault(fault.getBatteryPerFormance(),riskConfig,fault);
                    loadRiskFault(fault.getBatteryPerFormance(),fault.getVin(),"ALARM006",riskConfig,fault);
                    break;
                case "ALARM007":
                    //loadRiskFault(fault.getBatteryTempDiffLargeAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getBatteryTempDiffLargeAlarm(),fault.getVin(),"ALARM007",riskConfig,fault);
                    break;
                case "ALARM008":
                    //loadRiskFault(fault.getBatteryUniformityBadAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getBatteryUniformityBadAlarm(),fault.getVin(),"ALARM008",riskConfig,fault);
                case "ALARM010":
                    //loadRiskFault(fault.getBatterysVoltageHigherAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getBatterysVoltageHigherAlarm(),fault.getVin(),"ALARM010",riskConfig,fault);
                    break;
                case "ALARM011":
                    //loadRiskFault(fault.getBatterysVoltageLowerAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getBatterysVoltageLowerAlarm(),fault.getVin(),"ALARM011",riskConfig,fault);
                    break;
                case "ALARM012":
                    //loadRiskFault(fault.getBatteryBoxMismatchFault(),riskConfig,fault);
                    loadRiskFault(fault.getBatteryBoxMismatchFault(),fault.getVin(),"ALARM012",riskConfig,fault);
                    break;
                case "ALARM013":
                    //loadRiskFault(fault.getCanCmmunicationFault(),riskConfig,fault);
                    loadRiskFault(fault.getCanCommunicationFault(),fault.getVin(),"ALARM013",riskConfig,fault);
                    break;
                case "ALARM014":
                    //loadRiskFault(fault.getCanCommunicationFault0fStorage(),riskConfig,fault);
                    loadRiskFault(fault.getCanCommunicationFault0fStorage(),fault.getVin(),"ALARM014",riskConfig,fault);
                    break;
                case "ALARM015":
                    //loadRiskFault(fault.getChargeStatusFault(),riskConfig,fault);
                    loadRiskFault(fault.getChargeStatusFault(),fault.getVin(),"ALARM015",riskConfig,fault);
                    break;
                case "ALARM016":
                    //loadRiskFault(fault.getChargingGunConnectFault(),riskConfig,fault);
                    loadRiskFault(fault.getChargingGunConnectFault(),fault.getVin(),"ALARM016",riskConfig,fault);
                    break;
                case "ALARM017":
                    //loadRiskFault(fault.getDcStatusAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getDcStatusAlarm(),fault.getVin(),"ALARM017",riskConfig,fault);
                    break;
                case "ALARM018":
                    //loadRiskFault(fault.getDischargeCurrentBiggerAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getDischargeCurrentBiggerAlarm(),fault.getVin(),"ALARM018",riskConfig,fault);
                    break;
                case "ALARM019":
                    //loadRiskFault(fault.getElectricControOverTemp(),riskConfig,fault);
                    loadRiskFault(fault.getElectricControOverTemp(),fault.getVin(),"ALARM019",riskConfig,fault);
                    break;
                case "ALARM020":
                    //loadRiskFault(fault.getElectricOverSpeed(),riskConfig,fault);
                    loadRiskFault(fault.getElectricOverSpeed(),fault.getVin(),"ALARM020",riskConfig,fault);
                    break;
                case "ALARM021":
                    //loadRiskFault(fault.getElectricOverTemp(),riskConfig,fault);
                    loadRiskFault(fault.getElectricOverTemp(),fault.getVin(),"ALARM021",riskConfig,fault);
                    break;
                case "ALARM022":
                    //loadRiskFault(fault.getInputDcOverCurrent(),riskConfig,fault);
                    loadRiskFault(fault.getInputDcOverCurrent(),fault.getVin(),"ALARM022",riskConfig,fault);
                    break;
                case "ALARM023":
                    //loadRiskFault(fault.getInsulationFault(),riskConfig,fault);
                    loadRiskFault(fault.getInsulationFault(),fault.getVin(),"ALARM023",riskConfig,fault);
                    break;
                case "ALARM024":
                    //loadRiskFault(fault.getMonomerTempHigherAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getMonomerTempHigherAlarm(),fault.getVin(),"ALARM024",riskConfig,fault);
                    break;
                case "ALARM025":
                    //loadRiskFault(fault.getMonomerVoltageHigherAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getMonomerVoltageHigherAlarm(),fault.getVin(),"ALARM025",riskConfig,fault);
                    break;
                case "ALARM026":
                    //loadRiskFault(fault.getMonomerVoltageLowerAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getMonomerVoltageLowerAlarm(),fault.getVin(),"ALARM026",riskConfig,fault);
                    break;
                case "ALARM027":
                    //loadRiskFault(fault.getObcCommunicationFault(),riskConfig,fault);
                    loadRiskFault(fault.getObcCommunicationFault(),fault.getVin(),"ALARM027",riskConfig,fault);
                    break;
                case "ALARM028":
                    //loadRiskFault(fault.getOverTempFault(),riskConfig,fault);
                    loadRiskFault(fault.getOverTempFault(),fault.getVin(),"ALARM028",riskConfig,fault);
                    break;
                case "ALARM029":
                    //loadRiskFault(fault.getSocHigherAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getSocHigherAlarm(),fault.getVin(),"ALARM029",riskConfig,fault);
                    break;
                case "ALARM030":
                   // loadRiskFault(fault.getSocJumpFault(),riskConfig,fault);
                    loadRiskFault(fault.getSocJumpFault(),fault.getVin(),"ALARM030",riskConfig,fault);
                    break;
                case "ALARM031":
                    //loadRiskFault(fault.getSocLowerAlarm(),riskConfig,fault);
                    loadRiskFault(fault.getSocLowerAlarm(),fault.getVin(),"ALARM031",riskConfig,fault);
                    break;
                default:
                    break;
            }
        }catch (Exception e){
            logger.info("数据上报处理风险故障 Error Msg : {}", e.getMessage());
        }
    }



    private void updateRiskFault1(Map<String, String> lastMap) {
        C3RiskFault riskFault1 = new C3RiskFault();
        riskFault1.setEventId(lastMap.get("eventId"));
        riskFault1.setFaultLevel(Integer.parseInt(lastMap.get("riskLevel")));
        riskFault1.setVin(lastMap.get("vin"));
        riskFault1.setVehicleEquipment(lastMap.get("vehicleEquipment"));
        riskFault1.setFaultType(lastMap.get("riskType"));
        riskFault1.setType(lastMap.get("type"));
        DateUtil.parse(lastMap.get("startTime"),DateUtil.DATE_TIME);
        riskFault1.setStartTime(DateUtil.parse(lastMap.get("startTime"),DateUtil.DATE_TIME));
        riskFault1.setEndTime(DateUtil.parse(lastMap.get("endTime"),DateUtil.DATE_TIME));
        riskFault1.setEquipmentFaultItem(lastMap.get("equipmentRiskItem"));
        riskFaultService.insert(riskFault1);
    }

    private void loadRiskFault(int vehicleFault,String vin,String riskType,C3RiskConfiguration riskConfig,C3ReportCarFault fault){
//        if (level<riskConfiguration.getRiskLevel()){
//            return;
//        }else if (level>riskConfiguration.getRiskLevel()){
//            updateRiskFault(riskConfiguration,fault,"fault");
//        }else{
//            updateRiskFault(riskConfiguration,fault,"risk");
//        }
        // 风险/故障标准值
        String eventId = riskConfig.getEventId();
        int riskLevel = riskConfig.getRiskLevel();
        Map<String, String>  map = new HashMap<>(7);
        map.put("eventId", eventId);
        map.put("vin", fault.getVin());
        map.put("vehicleEquipment", riskConfig.getVehicleEquipment());
        map.put("riskType", riskConfig.getRiskType());
        map.put("equipmentRiskItem", riskConfig.getEquipmentRiskItem());

        //取出上次的map
        Map<String, String> lastMap = maps.get(riskType+"-"+vin);

        //上次的map为空，并且此次的值小于标准值
        if (vehicleFault < riskLevel && org.springframework.util.CollectionUtils.isEmpty(lastMap)){
            return;
        }
        //第一次出现
        if (vehicleFault >= riskLevel && org.springframework.util.CollectionUtils.isEmpty(lastMap)){
            map.put("startTime", DateUtil.format(new Date(), DateUtil.DATE_TIME));
            map.put("endTime", DateUtil.format(new Date(), DateUtil.DATE_TIME));
            map.put("riskLevel", String.valueOf(vehicleFault));
            maps.put(riskType+"-"+vin,map);
            return;
        }
        // 风险判断
        int riskLevel1 = Integer.parseInt(lastMap.get("riskLevel"));//上次上报的风险值
        if (riskLevel1 != vehicleFault) {
            updateRiskFault1(lastMap);
            lastMap.put("startTime", DateUtil.format(new Date(), DateUtil.DATE_TIME));
        }
        lastMap.put("endTime", DateUtil.format(new Date(), DateUtil.DATE_TIME));
        lastMap.put("riskLevel", String.valueOf(vehicleFault));
        if (riskLevel == vehicleFault) {
            lastMap.put("type", "20");
        }
        if (vehicleFault > riskLevel) {
            lastMap.put("type", "30");
        }
        maps.put(riskType + "-" + vin, lastMap);
        return;
    }

    /**
     * 新增或更新风险故障记录表
     */
    private void updateRiskFault(C3RiskConfiguration riskConfiguration,C3ReportCarFault fault,String type){
                //判断最近一次上报的是否为该风险事件
                EntityWrapper<C3RiskFault> riskFaultEntityWrapper = new EntityWrapper<>();
                if ("risk".equals(type)){
                    riskFaultEntityWrapper.eq("type",20);
                }
                if ("fault".equals(type)){
                    riskFaultEntityWrapper.eq("type",30);
                }
                riskFaultEntityWrapper.eq("vin",fault.getVin())
                        .eq("event_id",riskConfiguration.getEventId())
                        .where("now() <= date_add(end_time,INTERVAL 1 MINUTE)")
                        .orderBy("id",false)
                        .last("limit 0,1");
                long start = System.currentTimeMillis();
                C3RiskFault riskFault=riskFaultService.selectOne(riskFaultEntityWrapper);
                long end =System.currentTimeMillis();
                logger.info("查询Time:{}",end-start);
                //查询是否上报过，上报过就更新结束时间，否则就新增
                if (Objects.nonNull(riskFault) ){
                    EntityWrapper<C3RiskFault> ew1 = new EntityWrapper<>();
                    ew1.eq("id",riskFault.getId());
                    riskFault.setEndTime(new Date());
                   // baseMapper.insert(c3ReportEventInfo);
                    long start1 = System.currentTimeMillis();
                    riskFaultService.update(riskFault,ew1);
                    long end1 =System.currentTimeMillis();
                    logger.info("更新Time:{}",end1-start1);
                }else {
                    C3RiskFault riskFault1 = new C3RiskFault();
                    riskFault1.setEventId(riskConfiguration.getEventId());
                    riskFault1.setVin(fault.getVin());
                    riskFault1.setVehicleEquipment(riskConfiguration.getVehicleEquipment());
                    riskFault1.setFaultType(riskConfiguration.getRiskType());
                    riskFault1.setStartTime(new Date());
                    riskFault1.setEndTime(new Date());
                    riskFault1.setEquipmentFaultItem(riskConfiguration.getEquipmentRiskItem());
                    if ("risk".equals(type)){
                        riskFault1.setType("20");
                        riskFault1.setFaultLevel(riskConfiguration.getRiskLevel());
                    }if ("fault".equals(type)){
                        riskFault1.setType("30");
                        riskFault1.setFaultLevel(riskConfiguration.getRiskLevel()+1);
                    }
                    long start2 = System.currentTimeMillis();
                    riskFaultService.insert(riskFault1);
                    long end2 =System.currentTimeMillis();
                    logger.info("插入Time:{}",end2-start2);
                }
    }

}
